﻿using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using System.Xml;

// -----------------------------------------------------------------------
// <copyright file="$safeitemrootname$.cs" company="$registeredorganization$">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------
namespace MenuGame2DXNA
{
    public class Bomb : VisibleGameEntity
    {
        /// <summary>
        /// Trạng thái của bom
        /// </summary>
        public bool State
        {
            get;
            set;
        }
        /// <summary>
        /// Thời gian bắt đầu nổ
        /// </summary>
        private int timeStart;
        /// <summary>
        /// Thời gian chờ phát nổ
        /// </summary>
        private int timeLife;
        /// <summary>
        /// Vị trí trên ma trận bản đồ
        /// </summary>
        public Point PIndex
        {
            get;
            set;
        }

        /// <summary>
        /// Ma trận vật cản bản đồ
        /// </summary>
        private short[,] Obstructions;
        /// <summary>
        /// Lớp quản lý Vật phẩm
        /// </summary>
        private Tiles bootyManager;
        /// <summary>
        /// 
        /// </summary>
        private List<Point> listPIndex;
        /// <summary>
        /// Lớp quản lý nội dung
        /// </summary>
        private ContentManager contentManager;
        /// <summary>
        /// Tên file xml
        /// </summary>
        private string fileNameXmlExplosion;
        /// <summary>
        /// 
        /// </summary>
        private List<int> ListNumberOfBomb;
        /// <summary>
        /// 
        /// </summary>
        private BombManager bombManager;
        private bool FlagLeft;
        private bool FlagRight;
        private bool FlagDown;
        private bool FlagUp;
        private bool flagExp;


        private Vector2 SizeCell;
        /// <summary>
        /// Gets or sets a value indicating whether [flag exp].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [flag exp]; otherwise, <c>false</c>.
        /// </value>
        public bool FlagExp
        {
            get { return flagExp; }
            set { 
                
                if (!FlagExp)
                    timetick = 0;
                flagExp = value;
            }
        }
        /// <summary>
        /// Gets or sets the index.
        /// </summary>
        /// <value>
        /// The index.
        /// </value>
        public int Index
        {
            get;
            set;
        }

        /// <summary>
        /// 
        /// </summary>
        private int burstRadius;
        //Định nghĩa gọi các hàm sự kiện bom nổ
        public delegate void Explosion_handle(object sender);
        public event Explosion_handle explosion_event;

        private sMainGame MainGame;


        public Bomb(
            GameTime _gameTime, 
            ContentManager _contentManager, 
            string[] _strTextures, 
           
            Point _pIndex, 
            Tiles _bootyManager, 
            short[,] _obstructions,
            BombManager _bombManager,
            Vector2 _sizeCell, 
            string _fileNameXmlExplosion,
            int _burstRadius, 
            int _timeLife,
            sMainGame _mainGame
            )
        {
            MainGame = _mainGame;
            bombManager = _bombManager;
            bootyManager = _bootyManager;
            Obstructions = _obstructions;
            contentManager = _contentManager;
            fileNameXmlExplosion = _fileNameXmlExplosion;
            listPIndex = new List<Point>();
            SizeCell = _sizeCell;
           
            PIndex = _pIndex;

            // chua nổ
            flagExp = false;

            TopLeft = new Vector2(20, 30);
            PositionStart = new Vector2(PIndex.Y * SizeCell.X, PIndex.X * SizeCell.Y); 
            State = false;
            timeStart = _gameTime.TotalGameTime.Milliseconds;
            timeLife = _timeLife;
            burstRadius = _burstRadius;
            ListNumberOfBomb = new List<int>();
            
            ObjectVisible = new List<Sprite>();
            Texture2D[] texturesBomb = new Texture2D[_strTextures.Length];
            for(int i =0 ;i< _strTextures.Length ; i++)
            {
                texturesBomb[i] = _contentManager.Load<Texture2D>(_strTextures[i]);
            }
            Sprite temp = new AutomatedSprite(texturesBomb, PositionStart);
            listPIndex.Add(PIndex);
            ObjectVisible.Add(temp);
            nObjectVisible = 1;
            FlagDown = true;
            FlagLeft = true;
            FlagRight = true;
            FlagUp = true;
            ListNumberOfBomb.Add(1);
            //add sau vu no
            
           
        }

        /// <summary>
        /// Explosions the specified RAD.
        /// </summary>
        /// <param name="Rad">The RAD.</param>
        private void Explosion(int Rad)
        {
            //LoadMapCell From file
            XmlDocument xdomMapCell = new XmlDocument();
            
            
             xdomMapCell.Load(fileNameXmlExplosion);
            
            XmlElement xmlnTexture = (XmlElement)xdomMapCell.SelectSingleNode("Explosion/nTexture");
            XmlElement xmlprefixTexture = (XmlElement)xdomMapCell.SelectSingleNode("Explosion/prefixTexture");
            int nTexture = int.Parse(xmlnTexture.InnerText);
            Texture2D[] TextureExp = new Texture2D[nTexture];
            for (int i = 0; i < nTexture; i++)
                TextureExp[i] = contentManager.Load<Texture2D>("explosion/" + xmlprefixTexture.InnerText + i.ToString("00"));
            if (Rad == 0)
            {
                Vector2 tIndex = new Vector2(PIndex.Y * SizeCell.X, PIndex.X * SizeCell.Y);
                Sprite tExp = new AutomatedSprite(TextureExp, tIndex);
                ObjectVisible.Add(tExp);
                listPIndex.Add(PIndex);
                CheckDie(listPIndex[listPIndex.Count - 1]);
            }

            else
            {

                // qua phải
                if (FlagRight && PIndex.Y + Rad >= 0 && PIndex.Y + Rad < 11)
                {
                    if (Obstructions[PIndex.X, PIndex.Y + Rad] > 0 &&
                        bootyManager[new Point(PIndex.X, PIndex.Y + Rad)] == 0 &&
                        bombManager.FindBomb(new Point(PIndex.X, PIndex.Y + Rad)) < 0
                        )
                       { 
                        FlagRight = false;
                    }
                    else
                    {
                        Vector2 temPIndex = new Vector2((PIndex.Y + Rad) * SizeCell.X, PIndex.X * SizeCell.Y);
                        Sprite tempExp = new AutomatedSprite(TextureExp, temPIndex);

                        ObjectVisible.Add(tempExp);
                        CheckDie(listPIndex[listPIndex.Count - 1]);
                        listPIndex.Add(new Point(PIndex.X, PIndex.Y + Rad));

                       
                    }
                    if (bootyManager[new Point(PIndex.X, PIndex.Y + Rad)] > 0)
                        FlagRight = false;
                    
                }
                // qua trái


                if (FlagLeft && PIndex.Y - Rad >= 0 && PIndex.Y - Rad < 11)
                {
                    if (Obstructions[PIndex.X, PIndex.Y - Rad] > 0 &&
                        bootyManager[new Point(PIndex.X, PIndex.Y - Rad)] == 0 &&
                        bombManager.FindBomb(new Point(PIndex.X, PIndex.Y - Rad)) < 0
                        )
                    {
                        FlagLeft = false;
                    }
                    else
                    {
                        Vector2 temPIndex = new Vector2((PIndex.Y - Rad) * SizeCell.X, PIndex.X * SizeCell.Y);
                        Sprite tempExp = new AutomatedSprite(TextureExp, temPIndex);
                        ObjectVisible.Add(tempExp);
                        listPIndex.Add(new Point(PIndex.X, PIndex.Y - Rad));
                        CheckDie(listPIndex[listPIndex.Count - 1]);
                    }
                    if (bootyManager[new Point(PIndex.X, PIndex.Y - Rad)] > 0)
                        FlagLeft = false;
                   
                }

                // Xuóng dưới
              

                if (FlagDown && PIndex.X + Rad >= 0 && PIndex.X + Rad < 11)
                {
                    if (Obstructions[PIndex.X + Rad, PIndex.Y] > 0 &&
                        bootyManager[new Point(PIndex.X + Rad, PIndex.Y)] == 0 &&
                        bombManager.FindBomb(new Point(PIndex.X + Rad, PIndex.Y)) < 0
                        )
                        FlagDown = false;
                    else
                    {
                        Vector2 temPIndex = new Vector2((PIndex.Y) * SizeCell.X, (PIndex.X + Rad) * SizeCell.Y);
                        Sprite tempExp = new AutomatedSprite(TextureExp, temPIndex);
                        ObjectVisible.Add(tempExp);                           
                        listPIndex.Add(new Point(PIndex.X + Rad, PIndex.Y));
                        CheckDie(listPIndex[listPIndex.Count - 1]);
                    }
                    if (bootyManager[new Point(PIndex.X + Rad, PIndex.Y)] > 0)
                        FlagDown = false;
                   
                }

                if (FlagUp && PIndex.X - Rad >= 0 && PIndex.X - Rad < 11)
                {
                    if (Obstructions[PIndex.X - Rad, PIndex.Y] > 0 &&
                        bootyManager[new Point(PIndex.X - Rad, PIndex.Y)] == 0 &&
                        bombManager.FindBomb(new Point(PIndex.X - Rad, PIndex.Y)) < 0       
                        )
                        FlagUp = false;
                    else
                    {
                        Vector2 temPIndex = new Vector2((PIndex.Y) * SizeCell.X, (PIndex.X - Rad) * SizeCell.Y);
                        Sprite tempExp = new AutomatedSprite(TextureExp, temPIndex);
                        ObjectVisible.Add(tempExp);                        
                        listPIndex.Add(new Point(PIndex.X - Rad, PIndex.Y));
                        CheckDie(listPIndex[listPIndex.Count - 1]);
                    }
                    if (bootyManager[new Point(PIndex.X - Rad, PIndex.Y)] > 0)
                        FlagUp = false;
                   
                }
                
            }
           
            nObjectVisible = ObjectVisible.Count;
            
            ListNumberOfBomb.Add(nObjectVisible);
        }

        int timetick = 0;
        int TimePineline = 32;
        int RadiusBegin = 0;
        int Radi= 0;
        int nFrameExplosion = 35;
        int TimeChangeFramExp = 1;
        /// <summary>
        /// Updates the specified game time.
        /// </summary>
        /// <param name="gameTime">The game time.</param>
        /// <param name="color">The color.</param>
        private void CheckDie(Point pIndex)
        {
            if (MainGame.MainCharacter.pIndex.Equals(pIndex))
            {
                MainGame.MainCharacter.Destroy();
            }
            foreach (Enemy e in MainGame.Enemy)
            {
                if (e.pIndex.Equals(pIndex))
                {
                    e.Destroy();
                }
            }
        }
        public override void Update(GameTime gameTime, Color color)
        {
            ObjectVisible[0].Color = color;
            timetick++;
            if (!flagExp)
            {

                if (timetick <= timeLife / 16)
                {
                    if (timetick % 15 == 0)
                    {
                        ObjectVisible[0].Update(gameTime);
                    }
                }
                else
                {
                    flagExp = true;
                    timetick = 0;
                }
            }
            else if (timetick <(nFrameExplosion * TimeChangeFramExp - TimePineline) * burstRadius + nFrameExplosion * TimeChangeFramExp)
            {
                if (timetick % TimeChangeFramExp == 0)
                {
                    if (timetick == 1)
                    {
                        Obstructions[PIndex.X, PIndex.Y] = 0;
                        SoundManager.Play("boom");
                    }
                    if (Radi > burstRadius)
                        Radi = burstRadius;
                    RadiusBegin = (timetick - nFrameExplosion * TimeChangeFramExp) / (nFrameExplosion * TimeChangeFramExp - TimePineline) + 1;
                    if (RadiusBegin < 0)
                        RadiusBegin = 0;
                    for (int i = ListNumberOfBomb[RadiusBegin]; i < ObjectVisible.Count; i++)
                    {
                        ObjectVisible[i].Update(gameTime);
                    }
                    // Hiển thị các vật phẩm
                    if (timetick == Radi * (nFrameExplosion * TimeChangeFramExp - TimePineline) + 1)
                    {                    
                        Explosion(Radi);
                       
                        for (int i = ListNumberOfBomb[RadiusBegin];i < listPIndex.Count; i++)
                        {
                            bootyManager.RemoveCell(listPIndex[i]);
                            if (i > 1)
                                bombManager.BombExplosion(listPIndex[i]);
                        }
                        Radi++;
                    }

                }

            }
            else
            {
                explosion_event(this);
            }
            
          
        }
        /// <summary>
        /// Updates the positon.
        /// </summary>
        public override void UpdatePositon()
        {
            for(int i = 0; i < nObjectVisible ; i++)
            {
                if(i == 0)

                ObjectVisible[i].Position = new Vector2((listPIndex[i].Y * SizeCell.X)+TopLeft.X, (listPIndex[i].X * SizeCell.Y)+TopLeft.Y);
                else
                    ObjectVisible[i].Position = new Vector2((listPIndex[i].Y * SizeCell.X) + TopLeft.X, (listPIndex[i].X * SizeCell.Y) + TopLeft.Y);
            }
        }
        /// <summary>
        /// Draws the specified game time.
        /// </summary>
        /// <param name="gameTime">The game time.</param>
        /// <param name="spriteBatch">The sprite batch.</param>
        public override void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            if (!FlagExp)
            {
                ObjectVisible[0].Draw(gameTime,spriteBatch);
            }
            else if (timetick <  (nFrameExplosion * TimeChangeFramExp - TimePineline) * burstRadius + nFrameExplosion * TimeChangeFramExp)
            {
                for (int i = ListNumberOfBomb[RadiusBegin]; i < ObjectVisible.Count; i++)
                    ObjectVisible[i].Draw(gameTime, spriteBatch);
            }
           
        }
    }
}
